#ifndef  __MEDIA_H__
#define __MEDIA_H__

#include <pthread.h>
#include <stdbool.h>
#include <semaphore.h>
#include <sys/ioctl.h>

#include <libmedia/play/fb_video_player.h>
#include <libmedia/media_previewer.h>
#include <libmedia/read/isp_video_reader.h>
#include <libmedia/read/vic_video_reader.h>
#include <libmedia/decode/turbo_jpeg_video_decoder.h>
#include <libmedia/encode/hw_h264_video_encoder.h>
#include <libmedia/encode/hw_jpeg_video_encoder.h>

#include <libmedia/decode/hw_h264_decoder.h>

#include <libhardware2/camera_pixel_format.h>
#include <libhardware2/rotator.h>

#include "media_message.h"
#include "media_ipc_msg.h"


#define MAX_MEDIA_DIR_SIZE (50)

#define DST_HIGH_RESOLUTION_WIDTH (1280)
#define DST_HIGH_RESOLUTION_HEIGHT (720)

#define HIGH_RESOLUTION_SCALE_1_WIDTH (853)
#define HIGH_RESOLUTION_SCALE_1_HEIGHT (480)

#define HIGH_RESOLUTION_SCALE_2_WIDTH (640)
#define HIGH_RESOLUTION_SCALE_2_HEIGHT (360)

#define HIGH_RESOLUTION_SCALE_3_WIDTH (480)
#define HIGH_RESOLUTION_SCALE_3_HEIGHT (272)

#define MAX_RECORD_FILE_NAME_LENGHT (128)

enum reader_type {
	MEDIA_READER_PHOTO_JPEG,
	MEDIA_READER_VIDEO_AVI,

	MAX_READER_TYPE_COUNT,
};

enum reader_state {
	READER_STATE_NONE = 0,
	READER_STATE_STOP,
	READER_STATE_PAUSE,
	READER_STATE_START,
	READER_STATE_CONTINUE, 
	READER_STATE_THUMBNAIL, 

	READER_STATE_SELECT_FILE,

	MAX_READER_STATE_COUNT,
};

enum record_type {
	RECORD_TYPE_PHOTO = 0,
	RECORD_TYPE_VIDEO,

	MAX_RECORD_TYPE_COUNT,
};

struct reader_proc {

	pthread_t thread_id;
	pthread_rwlock_t rw_lock;
	volatile bool thread_quit;
	struct message_queue* queue;

	enum reader_type reader_type;
	enum reader_state state;

	char file_name[MAX_RECORD_FILE_NAME_LENGHT];
	bool file_select;

	struct video_decoder* video_decoder;
	struct hw_h264_video_decoder_param decoder_param;
	struct media_demuxing * demuxing;
	uint64_t total_duration;
	uint64_t cur_duration;

	uint64_t frame_count;
	uint64_t frame_played;

	uint64_t start_time;
	uint64_t cur_time;
	uint64_t pts_time_usec;
};

struct record_proc{
	char name[MAX_RECORD_TYPE_COUNT][MAX_RECORD_FILE_NAME_LENGHT];
	uint64_t start_time;
	uint64_t current_time;

	union {
		uint8_t data;
		struct {
			uint8_t start_photo : 1; 
			uint8_t stop_photo : 1;

			uint8_t start_record : 1;
			uint8_t stop_record : 1; 
		}state;
	}record_state;

	pthread_rwlock_t rw_lock;
	pthread_t thread_id;
	volatile bool thread_quit;

#define MAX_RECORD_MESSAGE_QUEUE_COUNT (1)
	struct message_queue* queue;
};

struct scale_proc {

	pthread_t thread_id;
	pthread_rwlock_t rw_lock;

	volatile bool thread_quit;
	enum video_scale_up scale_step;
	bool enable_whiteblack;

	struct message_queue* queue;
};

struct rotater_proc {
	pthread_t thread_id;
	pthread_rwlock_t rw_lock;
	
	volatile bool thread_quit;
	enum video_rotate_angle rotate_angle;

#define MAX_ROTATE_MESSAGE_QUEUE_COUNT (1)
	struct message_queue* queue;
};

struct scale_step {
	int width;
	int height;
};

struct media_frame {
	struct video_frame* crop_frame;
	struct video_frame* mixer_scale_frame;
	struct video_frame* encode_src_frame;
};

enum camera_resolution_type {
	CAMERA_HIGH_RES,
	CAMERA_LOW_RES,

	MAX_CAMERA_RES_COUNT,

	CAMERA_RES_NONE,
};

struct media_param {
	int width;
	int height;
	enum camera_resolution_type resolution_type;
	char media_dir[MAX_MEDIA_DIR_SIZE];
};

struct media_mode_proc {

	union media_state {
		uint32_t value;
		struct {
			bool media_preview_start:1;
			bool media_play_start:1;
		}state;

	}mode_state;
	pthread_spinlock_t spin_lock;
};

struct media_encoder {
	struct hw_h264_video_encoder_param  encoder_param;
	struct video_encoder* video_encoder;
};

struct media_camera {
	char name[20];
	struct v4l2_camera *camera;
    struct video_decoder *jpeg_decoder;
	struct turbo_jpeg_video_decoder_param jpeg_decoder_param;

	volatile bool camera_opened;
	volatile bool camera_online;
	volatile bool camera_error;
	pthread_mutex_t  mutex;
};

struct gsensor {
	int16_t x;
	int16_t y;
	int16_t z;

	int16_t  angle_num[10];
	int16_t pos;
	int16_t angle_cnt;	
};

struct media{	

	struct media_param media_param;

	struct media_mode_proc media_mode_proc;

	struct media_previewer_param previewer_param;
	struct fb_video_player_param fb_param;
	struct media_camera  camera;
	struct media_frame media_frame;
	struct media_previewer* previewer;

	struct media_encoder encoder;
	struct scale_proc scale_proc;
	struct rotater_proc rotater_proc;
	struct record_proc  record_proc;
	struct reader_proc reader_proc;
	struct gsensor gsensor;
};

extern int media_start(void);
extern void media_stop(void);

extern int media_previewer_start(void);
extern void media_previewer_stop(void);

extern int media_reader_start(void);
extern void media_reader_stop(void);

extern void media_set_video_resolution(int width, int height);
extern void media_set_video_rotater(enum rotator_angle angle);
extern void media_set_video_scale_factor(enum video_scale_up factor);

extern void set_video_scale(enum video_scale_up scale_factor);
extern void set_video_rotater_angle(enum video_rotate_angle angle);

extern int set_record_video_state(bool state, char* filename);
extern int set_record_photo_state(bool state, char* filename);
extern bool get_record_video_state(void);
extern bool get_record_photo_state(void);

extern struct message_queue* get_action_message_queue(enum video_action action);
extern struct media_mode_proc get_media_mode(void);
extern bool is_media_previewer_start(void);
extern void timer_delay_ms(int timeout_ms);

#endif 
